using System;
using System.Collections.Generic;
using FluentNHibernate;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Testing;
using NHibernate;
using NHibernate.Cfg;
using NHibernate.Tool.hbm2ddl;
using NUnit.Framework;

	public  class FixtureBase
	{
		protected SessionSource SessionSource { get; set; }
		protected ISessionFactory SessionFactory { get; set; }
	    protected ISession Session { get; private set; }

		public void Profile(string msg)
		{
			Console.WriteLine(string.Format("{0} {1}", DateTime.Now, msg));
		}

		private ISessionFactory CreateSessionFactory()
		{
			Profile("CreateFactory 1");
			var v = Fluently.Configure();
			Profile("CreateFactory 3");
			v = v
			  .Database(
				SQLiteConfiguration.Standard.InMemory
				//  .UsingFile(fileName)
			  );
			Profile("CreateFactory 3");
			v = v
			  .Mappings(m =>
				m.FluentMappings.AddFromAssemblyOf<ProjectMap>());

			Profile("CreateFactory 4");
			v = v
			  .ExposeConfiguration(BuildSchema);


			Profile("CreateFactory 5");
			var result = v.BuildSessionFactory();

			Profile("CreateFactory 6");
			return result;
		}

		private static void BuildSchema(Configuration config)
		{
			// this NHibernate tool takes a configuration (with mapping info in)
			// and exports a database schema from it
			new SchemaExport(config)
				.Create(false, true);
		}

		[SetUp]
		public void SetupContext()
		{
			//var cfg = Fluently.Configure().Database(SQLiteConfiguration.Standard.InMemory);
			SessionFactory = CreateSessionFactory();
			//IDictionary<string, string> config = cfg.BuildConfiguration().Properties;
			//SessionSource = new SessionSource(config, new TestModel());
			//Session = SessionSource.CreateSession();
			Session = SessionFactory.OpenSession();
			SessionSource.BuildSchema(Session);
		}
		[TearDown]
		public void TearDownContext()
		{
			Profile("TearDown Enter");
			Session.Close();
			Session.Dispose();
			Profile("TearDown Leave");
		}
	}
	[TestFixture]
	public class NunitPersistnceTests : FixtureBase
	{
		[Test]
		public void TestProjectMapWorksCorrectly()
		{
			var prj1 = new Project
			{
				Name = "Prj1",
			};
			var prj2 = new Project
			{
				Name = "Prj2",
			};
			Session.Save(prj1);
			Session.Save(prj2);

			var tasks = new List<Task>
			 {
				new Task{Id = 1, Name = "Task1", Project = prj1},
				new Task{Id = 2, Name = "Task2", Project = prj2},
			 };

			new PersistenceSpecification<Project>(Session)
				.CheckProperty(c => c.Name, "smth")
				.CheckList(c => c.Tasks, tasks)
				.VerifyTheMappings();
		}

		[Test]
		public void TestTaskMapWorksCorrectly()
		{
			Profile("Test Enter");
			var project = new Project
			{
				Name = "prj",
			};
			new PersistenceSpecification<Task>(Session)
				.CheckProperty(p => p.Name, "test")
				.CheckReference(p => p.Project, project)
				.VerifyTheMappings();
			Profile("Test Leave");
		}
	}
